﻿package net.molchat.android.media;


import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;

import net.molchat.android.R;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;


//========================================================= Управление ресурсами
/**
 * Содержит информацию об используемых медиа-ресурсах. <br />
 * Управляет: <br />
 * - загрузкой и выгрузкой ресурсов; <br />
 * - помещением ресурсов в кеш и извлечением из него. <br />
 */
public final class ResMan {

// =================================================================== Константы
public static final char CHAR = '#'; // Символ начала ресурса
public static final int MAX_RES = 128; // максимальное кол-во хранимых в памяти ресурсов
public static final Long UNK_RES_NUM = Long.valueOf(0); // Номер ресурса "неизвестный ресурс"
public static final String RES_PATH = "/res/"; // Local resource path prefix


//======================================================================= Static
public static Resources resources; // Android application resources


//=================================================================== Переменные
private ResCache resCache; //Resource cache 


private InputStream data;

public Hashtable res = new Hashtable(MAX_RES); // Все ресурсы

public int smlMaxW; // Максимальная ширина смайлов
public int smlMaxH; // Максимальная высота


// =============================================================== Инициализация
public ResMan() {

}


public void init(Resources resources) {

	Log.v("ResMan.init", "=====");
	ResMan.resources = resources;
	loadSmiles();
	loadIcons();
}


//==================================================================== loadIcons
private void loadIcons() {

}


//======================================================================= getRes
public Resource getRes(long id) {

	Resource res = resCache.getRes(id);
	if (res != null) {
		return res;
	}

	// load from server here

	return null;
}


// ================================================= Загрузить картинку из файла
// FIXME check if this method is used somewhere
private Bitmap loadImage(int imgType, String resource) {

	Bitmap img = null;

	//	Log.v("ResMan.loadImage", "Image file: " + "/res/s/" + resource + ".png");

	try {

		switch (imgType) {
			case Resource.TYPE_PIC_STATIC:
				// FIXME conversion should be created from "file" to resource constant
				// see http://stackoverflow.com/questions/9156698/how-to-get-images-dynamiclly-from-drawable-folder
				// FIXME set image size somewhere
				img = BitmapFactory.decodeResource(ResMan.resources, R.drawable.zz);
				break;
			case Resource.TYPE_PIC_ANI:
				// FIXME conversion should be created from "file" to resource constant
				// see http://stackoverflow.com/questions/9156698/how-to-get-images-dynamiclly-from-drawable-folder
				img = BitmapFactory.decodeResource(ResMan.resources, R.drawable.zz);
				break;
		}

	} catch (Exception e) {
		Log.e("ResMan.getImgFile", "Не могу загрузить картинку: type=" + imgType
				+ ", resource=" + resource + ".png", e);
	}

	return img;
}


// ============================================================ Загрузка смайлов
private void loadSmiles() {

	try {

		//		data = this.getClass().getResourceAsStream("/res/sml.txt");
		data = resources.openRawResource(R.raw.sml);

		int id;

		do {

			// Ищем знак начала смайла (#)
			do {
			} while (data.read() != '#');

			// Набор символов отображения смайла
			id = readInt();
			//			Log.v("SmileList.loadSmiles", "sym=" + sym);

			Pic p = new Pic();
			p.setID(0, id);

			p.alt = readString();
			String file = readString();

			// Анимация
			if (data.read() == ' ') { // Смайл анимирован

				p.type = Resource.TYPE_PIC_ANI;
				p.img = loadImage(Resource.TYPE_PIC_ANI, file);

				p.w = readInt();
				p.h = readInt();

				// Кадры и длительность

				// Количество кадров
				int frameNum = readInt();
				p.seq = new byte[frameNum << 1];

				// Кадры
				for (int q = 0; q < frameNum; ++q) {
					p.seq[q << 1] = (byte) readInt(); // Номер кадра
					p.seq[(q << 1) + 1] = (byte) readInt(); // Длительность
				}

			} else { // Смайл статичный
				p.type = Resource.TYPE_PIC_STATIC;
				p.img = loadImage(Resource.TYPE_PIC_STATIC, file);
				p.w = p.img.getWidth();
				p.h = p.img.getHeight();
			}

			if (id == 0) { // Смайл служебный, для неизвестных смайлов
				p.type = Resource.RES_SML_UNK;
			}

			res.put(p.id, p);

			if (p.w > smlMaxW) {
				smlMaxW = p.w;
			}
			if (p.w > smlMaxH) {
				smlMaxH = p.w;
			}

		} while (id != 0);

		data.close();

		Log.v("ResMan.loadSmiles", "smlMaxW=" + smlMaxW + ", smlMaxH=" + smlMaxH);

	} catch (Exception e) {
		Log.e("ResMan.loadSmiles", "Ошибка чтения смайлов", e);
	}

}


// ============================================================== Прочесть число
private int readInt() throws IOException {

	int ret = 0;
	char ch;

	// Пропускаем не числа
	while (!((ch = (char) data.read()) >= '0' && ch <= '9'))
		;

	do {
		ret = (ret << 3) + ret + ret + ch - 0x30;
	} while ((ch = (char) data.read()) >= '0' && ch <= '9');

	return ret;
}


// ============================================================== Прочесть слово
private String readString() {

	char ch;
	StringBuffer textBuf = new StringBuffer(12);

	try {
		// Пропускаем пустоту
		while ((ch = (char) data.read()) <= ' ')
			;

		textBuf.append(ch);

		// Текстовое описание
		while ((ch = (char) data.read()) > ' ') {
			textBuf.append(ch);
		}

	} catch (IOException e) {
		Log.e("SmileList.readString", "Ошибка чтения строки", e);
	}

	return textBuf.toString();

}


//========================================================== Выдать ресурс по ID
public Resource getRes(Long id) {

	Resource res = (Resource) this.res.get(id);
	if (res != null) {
		return res;
	} else {
		return (Resource) this.res.get(UNK_RES_NUM);
	}

}


//=========================================================== Выдать все ресурсы
public Enumeration getAll() {

	return this.res.elements();
}


//=========================================================== Выдать все ресурсы
public int getLen() {

	return this.res.size();
}


//========================================================================= load
/**
 * Load resource from remote server. Server knows resource type.
 */
public Resource load(long id) {

	// TODO make method body
	return null;
}


/**
 * Load resource from local resource folder.
 * 
 * 
 * @param resType
 *          - Resource type.
 * @param path
 *          - local resource file path.
 * @param id
 *          - full resource id.
 * @return - Resource or null if there was file reading error.
 */
public Resource load(int resType, String path, Long id, String fileExt) {

	return load(resType, path, id, fileExt, -1, -1, null);
}


// TODO "load" methods needs more adequate names.
/**
 * Load resource from local resource folder.
 * 
 * 
 * @param resType
 *          - Resource type.
 * @param path
 *          - local resource file path.
 * @param id
 *          - full resource id.
 * @param w
 *          - Picture width.
 * @param h
 *          - Picture height.
 * @param seq
 *          - Animated picture sequence.
 * @return - Resource or null if there was file reading error.
 */
public Resource load(int resType, String path, Long id, String fileExt, int w,
		int h, byte[] seq) {

	Resource res = null;
	Pic resPic;

	switch (resType) {
		case Resource.TYPE_PIC_STATIC:
			resPic = new Pic();
			resPic.type = Resource.TYPE_PIC_STATIC;
			resPic.id = id;
			try {
				//				resPic.img = Image.createImage(RES_PATH + path + id + fileExt);
				resPic.img = BitmapFactory.decodeResource(ResMan.resources,
						R.drawable.zz);
				resPic.w = resPic.img.getWidth();
				resPic.h = resPic.img.getHeight();
				res = resPic;
			} catch (Exception e) {
				Log.e("ResLoader.load", "CAN'T create resource", e);
			}
			break;
		case Resource.TYPE_PIC_ANI:
			resPic = new Pic();
			resPic.type = Resource.TYPE_PIC_ANI;
			resPic.id = id;
			try {
				//			resPic.img = Image.createImage(RES_PATH + path + id + fileExt);
				resPic.img = BitmapFactory.decodeResource(ResMan.resources,
						R.drawable.zz);
				resPic.w = w;
				resPic.h = h;
				resPic.seq = seq;
				resPic.nextFrame(0);
				res = resPic;
			} catch (Exception e) {
				Log.e("ResLoader.load", "CAN'T create resource", e);
			}
			break;
		default:
			Log.e("ResLoader.load", "Unknown resource type requested: " + resType
					+ ", path = " + path + ", id = " + id + ", fileExt = " + fileExt
					+ ", size = " + w + " x " + h + ", seq = " + seq);
	}

	return res;
}


}
